﻿// -------------------------------------------------------------------------
//    @FileName         :    NFSessionUtil.cpp
//    @Author           :    gaoyi
//    @Date             :    24-8-23
//    @Email            :    445267987@qq.com
//    @Module           :    NFSessionUtil
//
// -------------------------------------------------------------------------

#include "NFSessionUtil.h"

#include <NFLogicConfig.h>
#include <NFComm/NFCore/NFRandom.hpp>

#include "NFRegisterCache.h"
#include "NFSession.h"
#include "NFWhiteListCache.h"

NFSession* NFSessionUtil::GetSessionObj(int iGlobalID)
{
    NFSession* pSession = NFSession::GetObjByGlobalId(iGlobalID);
    if (pSession && pSession->GetDelayStopTime() > 0)
        pSession = NULL;

    return pSession;
}

int NFSessionUtil::DestorySessionObj(NFSession* pSession, int iDelayMS)
{
    CHECK_NULL(0, pSession);

    if (iDelayMS == 0)
        pSession->SetWillDelete();
    else
        pSession->SetDelayStopTime(NF_ADJUST_TIMENOW_MS() + iDelayMS);

    return 0;
}

int NFSessionUtil::Tick()
{
    static NFSession::iterator m_lastIter = NFSession::Begin();
    for (int i = 0; i < MAX_TICK_SESSION_NUM_PER_Tick; i++)
    {
        if (!NFSession::IsValid(m_lastIter) || m_lastIter == NFSession::End())
        {
            m_lastIter = NFSession::Begin();
            if (m_lastIter == NFSession::End())
            {
                break;
            }
            if (i > NFSession::GetStaticUsedCount())
            {
                break;
            }
        }

        auto pSession = &*m_lastIter;
        CHECK_NULL(0, pSession);

        if (pSession->IsWillDelete())
        {
            m_lastIter = NFSession::Erase(m_lastIter);
            continue;
        }

        if (pSession->GetDelayStopTime() > 0)
        {
            if (pSession->GetDelayStopTime() < NF_ADJUST_TIMENOW_MS())
            {
                int iRetCode = pSession->SendConndStop();
                CHECK_RET(iRetCode, "CPacketSendUtil::SendToConndHead Failed");

                if (!pSession->GetPlayer())
                {
                    m_lastIter = NFSession::Erase(m_lastIter);
                    continue;
                }
                else
                {
                    pSession->SetDelayStopTime(0);
                }
            }
            ++m_lastIter;
            continue;
        }

        if (!pSession->GetPlayer() && 0 != pSession->GetLastActiveTime() &&
            pSession->GetLastActiveTime() + NFLogicConfig::Instance()->SessionHeartbeatTimeout() < NF_ADJUST_TIMENOW())
        {
            LOGSVR_INFO("session miss player, self:" << pSession << ", client heartbeat timeout,sessionid:" << pSession->GetGlobalId());

            int iRetCode = pSession->SendConndStop();
            CHECK_RET(iRetCode, "CPacketSendUtil::SendToConndHead Failed");

            m_lastIter = NFSession::Erase(m_lastIter);
            continue;
        }

        ++m_lastIter;
    }

    return 0;
}

int NFSessionUtil::IsRegisterLimit(NFSession* pSession, bool& bCanRegister)
{
    CHECK_NULL(0, pSession);
    bCanRegister = true;
    tbWriteList stWhiteList;
    stWhiteList.account_id = pSession->GetAccountID();
    if (NFLogicConfig::Instance()->IsForbidRegist())
    {
        if (!NFWhiteListCache::Instance()->IsInWhiteList(&stWhiteList))
        {
            bCanRegister = false;
            return 0;
        }
    }
    else if (NFLogicConfig::Instance()->IsRegistLimit())
    {
        if (!NFWhiteListCache::Instance()->IsInWhiteList(&stWhiteList))
        {
            if (pSession->GetPlatformType() == proto_ff::E_Account_Type_Local)
            {
                if (NFRegisterCache::Instance()->CheckRegNumFull())
                {
                    LOGSVR_ERROR("qq regist limit. config limit" << NFLogicConfig::Instance()->GetQQRegistLimit());
                    bCanRegister = false;
                    return 0;
                }
            }
            else if (pSession->GetPlatformType() == proto_ff::E_Account_Type_Wechat)
            {
                if (NFRegisterCache::Instance()->CheckRegNumFull())
                {
                    LOGSVR_ERROR("wechat regist limit. config limit:%d" <<  NFLogicConfig::Instance()->GetQQRegistLimit());
                    bCanRegister = false;
                    return 0;
                }
            }
        }
    }
    return 0;
}
